#include "gMatrix.h"
#include "main-tools.h"
#include <stdbool.h>

PGMatrix initGMatrix(int* _N, int _basevalue){
	PGMatrix result = (PGMatrix)malloc(sizeof(GMatrix));
	checkMalloc(result, "gMatrix.c:initGMatrix:1");
	result->N = _N;
	result->matrix = (int**)malloc(*_N*sizeof(int*));
	checkMalloc(result->matrix, "gMatrix.c:initGMatrix:2");
	int i, j;
	for (i=0; i<*_N; i++){
		result->matrix[i] = (int*)malloc(*_N*sizeof(int));
		checkMalloc(result->matrix[i], "gMatrix.c:initGMatrix:3");
		for (j=(i+1); j<*_N; j++)
			result->matrix[i][j] = _basevalue;
	}
	return result;
}

//TODO testing
void freeGMatrix(PGMatrix matrix){
	free(matrix->matrix);
	free(matrix);
}

PGMatrix cloneGMatrix(PGMatrix matrix){
	PGMatrix result=initGMatrix(matrix->N,0);
	int i,j;
	for (i=0;i<*result->N;i++){
		for (j=(i+1);j<*result->N;j++){
			result->matrix[i][j]=matrix->matrix[i][j];
		}
	}
	return result;
}

void printGMatrix(FILE* f, PGMatrix matrix){

	//fprintf(f,"Stampa dellaN:%d\n",*matrix->N);
	fprintf(f, "Matrix of Gatherings\n");
	fprintf(f, "i\\f|");
	int i;
	int j;
	for(i=0; i<*matrix->N; i++)
		fprintf(f, "%3d|", i+1);
	fprintf(f, "\n");
	for(i=0; i<*matrix->N; i++){
		fprintf(f, "%3d|", i+1);
		for (j=0; j<=i; j++)
			fprintf(f, "---|");
		for (j=i+1; j<*matrix->N; j++)
			if (matrix->matrix[i][j] == NOT_GATHERED)
				fprintf(f, " _ |");
			else
				fprintf(f, "%3d|", matrix->matrix[i][j]+1);
		fprintf(f, "\n");
	}
}

/* ---------------------------- QUERY ----------------------------------------*/

int whoGathersEdge(PGMatrix pgm, PedgeID pe){
	return pgm->matrix[pe->i][pe->j];
}

bool isEdgeGathered(PGMatrix pgm, PedgeID pe) {
	return pgm->matrix[pe->i][pe->j] != NOT_GATHERED;
}

bool amIGatheringEdge(PGMatrix pgm, PedgeID pe, int k) {
	return pgm->matrix[pe->i][pe->j] == k;
}

bool tryToGatherEdge(PGMatrix pgm, PedgeID pe, int k) {
	if (!isEdgeGathered(pgm, pe)){
		gatherEdge(pgm, pe, k);
		return true;
	}
	return false;
}

void gatherEdge(PGMatrix pgm, PedgeID pe, int k){
	pgm->matrix[pe->i][pe->j] = k;
}

bool releaseIfImGatheringEdge(PGMatrix pgm, PedgeID pe, int k) {
	if(amIGatheringEdge(pgm, pe, k)) {
		releaseGatherEdge(pgm, pe);
		return true;
	}
	return false;
}

void releaseGatherEdge(PGMatrix pgm, PedgeID pe) {
	gatherEdge(pgm, pe, NOT_GATHERED);
}
